﻿/**
 * InterfacesManager
 */
var fs = require('fs');
var pathModule = require('path');

/**
 * 接口文件解析
 * @param {string|JsonObject} path 接口文件地址或者json对象,如果是string则解析为文件地址加载文件内容解析,如果为object则直接解析规则
 * @param {string} encoding 接口文件编码
 * @param {bool} debug 调试
 * @return {interfacesManager} 
 */
var InterfacesManager = function (path,encoding,debug) {
    this._interfaces = {};
    this.debug = !!debug;
    this._encoding = encoding || "utf8";
    typeof path === 'string' ? this._loadProfilesFromFile(path) : this._loadProfiles(path);
}

//设置是否调试
InterfacesManager.prototype.debug = false;

/**
 * 从文件中加载接口配置
 * @param {string} path 接口配置文件地址
 */
InterfacesManager.prototype._loadProfilesFromFile = function (path) {
    path = pathModule.join(process.cwd(),path);
    this.debug && console.info("加载配置文件：" + path);
    var profiles = require(path);
    this._loadProfiles(profiles);
}

/**
 * 解析接口配置内容
 * @param {JsonObject} profiles 接口内容的json对象
 */
InterfacesManager.prototype._loadProfiles = function (profiles) {
    if (!profiles) return;
    this.debug && console.info('Title:', profiles.title, 'Version:', profiles.version);
    if (profiles.status === undefined) {
        throw new Error('没有默认加载方式[status]配置信息!');
    }
    this._status = profiles.status;
    var interfaces = profiles.interfaces || {};
    for (var id in interfaces) {
        this._addInterface(id, interfaces[id],profiles) && this.debug && console.info("接口" + id + "解析完成");
    }
    var interfaceFiles = profiles.interface_files || [];
    for (var filepath in interfaceFiles)
        this._loadInterfaceFile(profiles,interfaceFiles[filepath]);
}

/**
 * 增加一个接口
 * @param {string} id 接口ID
 * @param {JsonObject} prof 接口配置json对象
 * @param {object} profiles 全局配置信息
 * @return {bool}
 */
InterfacesManager.prototype._addInterface = function (id, prof, profiles) {
    if (!prof)
        return;
    if (!this._checkInterfaceId) {
        this.debug && console.warn("接口必须指定唯一的ID：" + id);
        return false;
    }
    prof.status = prof.status || this._status;
    prof.url = this._getUrl(id, prof, profiles);
    if (!prof.url) //没找到文件路径返回失败
        return false;
    prof.params = prof.params || {};
    if (Array.isArray(prof.params)) {
        var ps = prof.params;
        prof.params = {};
        for (var param in ps) {
            prof.params[ps[param]] = { type: "string" };
        }
    } else {
        for (var param in prof.params) {
            if (typeof prof.params[param] === 'string') {
                prof.params[param] = { "type": prof.params[param] };
            } else if (prof.params[param] === undefined) {
                prof.params[param] = { "type": prof.params[param] };
            }
        }
    }
    prof.cookies = prof.cookies ? true : false;
    prof.method = { POST: 'POST', GET: 'GET' }[ (prof.method || 'GET').toUpperCase() ] || "get";
    prof.timeout = parseInt(prof.timeout) || 5000;
    prof.encoding = prof.encoding || "utf8";
    prof.dataType = prof.dataType || "json";
    //HTTPS处理
    prof.rejectUnauthorized = prof.rejectUnauthorized  || profiles.rejectUnauthorized || false;
    prof.pfx = prof.pfx || profiles.pfx;
    prof.passphrase = prof.passphrase || profiles.passphrase;
    prof.cert = prof.cert || profiles.cert;
    prof.key = prof.key || profiles.key;
    this._interfaces[id] = prof;
    return true;
}

/**
 * 加载接口内容文件
 * @param {object} profiles 整体文件配置信息
 * @param {string} path 接口文件地址
 */
InterfacesManager.prototype._loadInterfaceFile = function (profiles, path) {
    path = pathModule.join(process.cwd(), this._joinPath(profiles, path));
    var prefix = pathModule.basename(path, pathModule.extname(path)); //获取接口文件名
    var prof = require(path) || {};
    for (var id in prof) {
        var prefixId = prefix+"." + id; //拼接接口ID。文件名.接口ID
        this._addInterface(prefixId, prof[id],profiles) && this.debug && console.info("接口" + id + "解析完成");
    }
}

/**
 * 检测接口ID是否有效
 * @param {string} id 接口ID
 * @return {bool}
 */
InterfacesManager.prototype._checkInterfaceId = function (id) {
    return !this._interfaces[id];
}

 /**
  *获取数据加载地址
   * @param {string} id 接口ID
   * @param {string} prof 接口配置配置信息
   * @param {object} profiles 全局配置信息
   * @return {bool}
   */
InterfacesManager.prototype._getUrl = function (id, prof, profiles) {
    profiles = profiles || {};
    path = (prof.urls || {})[prof.status];
    if (prof.status !== 'mock' && !path) {
        this.debug && console.error("接口" + id + "找不到数据加载地址[" + prof.status + "]");
        return undefined;
    }else if (prof.status === 'mock' && !path) {
        this.debug && console.info("接口" + id + "找不到数据加载地址[" + prof.status + "],加载默认配置地址");
        if (!profiles['rulePath']) {
            this.debug && console.error("找不到默认配置文件路径[rulePath],默认配置文件加载失败");
            return undefined;
        }
        path = pathModule.join(profiles['rulePath'].toString(), id + ".rule.json");
    }
    path = this._joinPath(profiles, path); //请求地址
    if (prof.status === 'mock' && !fs.existsSync(path)) {
        this.debug && console.error("找不到默认配置文件" + path + "不存在,接口" + id + "配置加载失败");
        return undefined;
    }
    return path;
}

/**
 * 获取接口信息
 * @param {string} id 接口ID
 * @return {jsonObject} 接口配置内容
 */
InterfacesManager.prototype.getInterface = function (id) {
    if (this._interfaces[id])
        return this._interfaces[id];
    throw new Error("接口" + id + "信息未找到");
}

/**
 * 处理文件地址，生成完整路径
 * @param {object} 整体配置信息
 * @param {string} 文件地址
 */
InterfacesManager.prototype._joinPath = function (profiles, path){
    path = path.replace(/::(.*?)::/g, function (m, n) {
        if (profiles[n]) {
            return profiles[n];
        }
        throw new Error("Can't find property ：" + n);
    });
    return path;
}

module.exports = InterfacesManager;